package com.cloudtasks;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

import com.cloudtasks.R;
import com.cloudtasks.AsyncFetchTask;
import com.cloudtasks.TaskAdapter;
import com.cloudtasks.TaskApplication;

import com.cloudtasks.DeviceRegistrar;
//import com.cloudtasks.R;
import com.cloudtasks.Util;
import com.cloudtasks.TaskApplication.TaskListener;
import com.cloudtasks.shared.CloudTasksRequestFactory;
import com.cloudtasks.shared.ItemProxy;
import com.cloudtasks.shared.ListProxy;
import com.cloudtasks.shared.ListRequest;
import com.cloudtasks.shared.TaskChange;
import com.cloudtasks.shared.TaskProxy;
import com.cloudtasks.shared.TaskRequest;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;

@TargetApi(9)
public class UsersDisplayActivity extends Activity{
    
	final Context myContext = this;
	private Cursor DBcursor;
	final static String TYPE_PAGE = "user";
	private Database mDb; 
	 private View progressBar;
	 private TaskAdapter adapter;
	 private AsyncFetchTask task;
	 private AsyncFetchList groc_list;
	 private AsyncFetchItem groc_item;
	 private AsyncSendTask send_task_thread;
	 private AsyncSendList send_list_thread;
	 private AsyncSendItem send_item_thread;
	 ListView lv;
	 long current_user_id = 0;  //Global current user id to update did
	 Queue<Long> users_ids = new ArrayDeque<Long>();
	 Queue<Long> list_ids = new ArrayDeque<Long>();
	 Queue<Long> item_ids = new ArrayDeque<Long>();
	 long current_list_id = 0;  //Global current user id to update did 
	 long current_item_id = 0;  //Global current user id to update did 
	 int lock=0; //My version of mutex for users
	 int lock2=0; //My version of mutex for lists
	 int lock3=0; //My version of mutex for items
	 static volatile int list_go = 0;
	 static volatile int item_go = 0;
	 static volatile int sync_var = 0;
	 static SynchronizedCounter sync_count = new SynchronizedCounter();
	// sync_count.setValue(0);

	 
	 /**
	     * A {@link BroadcastReceiver} to receive the response from a register or
	     * unregister request, and to update the UI.
	     */
	    private final BroadcastReceiver mUpdateUIReceiver = new BroadcastReceiver() {
	        @Override
	        public void onReceive(Context context, Intent intent) {
	            int status = intent.getIntExtra(DeviceRegistrar.STATUS_EXTRA,
	                    DeviceRegistrar.ERROR_STATUS);
	            String message = null;
	            if (status == DeviceRegistrar.REGISTERED_STATUS) {
	                message = getResources().getString(R.string.registration_succeeded);
	            } else if (status == DeviceRegistrar.UNREGISTERED_STATUS) {
	                message = getResources().getString(R.string.unregistration_succeeded);
	            } else {
	                message = getResources().getString(R.string.registration_error);
	            }

	            // Display a notification
	            SharedPreferences prefs = Util.getSharedPreferences(myContext);
	            String accountName = prefs.getString(Util.ACCOUNT_NAME, "Unknown");
	            Util.generateNotification(myContext, String.format(message, accountName));
	        }
	    };
	 
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.users_main);
        sync_count.setValue(0);
        
        try{            	
	        // Add Button ADD
	        Button addItem = (Button)findViewById(R.id.add_user_button);
	        Button syncItems = (Button)findViewById(R.id.sync_button);
	        progressBar = findViewById(R.id.title_refresh_progress);
	        addItem.setOnClickListener(addUserListener);  
	        syncItems.setOnClickListener(syncListener);
	        
	        // initialize the Database for this context
	        mDb = new Database(this);
	        mDb.open();
	        lv = (ListView) findViewById(R.id.users_listview);
	        DBcursor = mDb.fetchAllUsers();
	        lv.setAdapter(new SimpleCursorAdapter(this,  
	        	    android.R.layout.simple_list_item_1,
	        	    DBcursor,
	        	    new String[] {Database.KEY_NAME},
	        	    new int[] { android.R.id.text1}
	        	));
	        startManagingCursor(DBcursor);
	        
	        //Sync on start up
	        
	        SharedPreferences prefs = Util.getSharedPreferences(myContext);
	        String deviceRegistrationID = prefs.getString(Util.DEVICE_REGISTRATION_ID, null);
	        if (deviceRegistrationID == null) {
	            // Show the 'connect' screen if we are not connected
	        	MyTools.displayToastMessage(myContext, "You need to set up your account, click menu->Account");
	        } else {
	        	// progressBar.setVisibility(View.VISIBLE);
				 //fetchTasks(-1);
	        }
	     
	        // what happens when you click one entry in the ListView
	        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {  
				@Override
				public void onItemClick(AdapterView<?> av, View view,
						int pos, long id) {
					ListView lv = (ListView) findViewById(R.id.users_listview);	        		
	        		String name = ((TextView) view).getText().toString();
					Intent intent = new Intent(myContext, ListsDisplayActivity.class);
					intent.putExtra("uname", name);
					intent.putExtra("uid", lv.getAdapter().getItemId(pos));
					startActivity(intent);   
				}  
	        });  
	        // what happens when you click and hold on one entry in the ListView
	        lv.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener(){ 
	        	@Override 
	        	public boolean onItemLongClick(AdapterView<?> av, View view, int pos, long id) { 
	        		CustomDialog editPopup = new CustomDialog(myContext, mDb, DBcursor, "edit", TYPE_PAGE);
	        		ListView lv = (ListView) findViewById(R.id.users_listview);	        		
	        		editPopup.passNameID(lv.getAdapter().getItemId(pos));
	        		editPopup.show();
					return false;
	        	} 
	        }); 
        }
        catch(Exception e){
        	MyTools.displayToastMessage(myContext, e.toString());
        }
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        // Invoke the Register activity
        menu.getItem(0).setIntent(new Intent(this, AccountsActivity.class));
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	// TODO Auto-generated method stub
    	switch (item.getItemId()) {
		case R.id.menu_refresh:
			fetchTasks(-1);
			break;

		default:
			break;
		}
    	return super.onOptionsItemSelected(item);
    }

    
    
    /////////////// CLICK LISTENERS /////////////////
    /* Add Listener */
    private OnClickListener addUserListener = new OnClickListener(){
		public void onClick(View v){						
			// fetch the name of the user				
			try{
				CustomDialog addPopup = new CustomDialog(myContext, mDb, DBcursor, "add", TYPE_PAGE);
				addPopup.show();
			}
			catch(Exception e){
				MyTools.displayToastMessage(myContext,e.toString());	
			}
		}
	};
	
	
	
	 private OnClickListener syncListener = new OnClickListener(){
		public void onClick(View v){						
			// fetch the name of the user				
			try{
				//CustomDialog addPopup = new CustomDialog(myContext, mDb, DBcursor, "add", TYPE_PAGE);
				//addPopup.show();
				
			    SharedPreferences prefs = Util.getSharedPreferences(myContext);
		        String deviceRegistrationID = prefs.getString(Util.DEVICE_REGISTRATION_ID, null);
		        if (deviceRegistrationID == null) {
		            // Show the 'connect' screen if we are not connected
		        	MyTools.displayToastMessage(myContext, "You need to set up your account, click menu->Account");
		        } else {
		        	 progressBar.setVisibility(View.VISIBLE);
					 fetchTasks(-1);
		        }				
				
			}
			catch(Exception e){
				MyTools.displayToastMessage(myContext,e.toString());	
			}
		}
	};
	
	public void onDestroy() {
        super.onDestroy();
     
        mDb.close();
    }
	
	  public void fetchTasks(long id) {
	        //progressBar.setVisibility(View.VISIBLE);
	        if (task != null) {
	            task.cancel(true);
	        }
	        task = new AsyncFetchTask(this);
	        task.execute(id);
	    }
	  
	  public void fetchLists(long id) {
	        
	        if (groc_list != null) {
	            groc_list.cancel(true);
	        }
	        groc_list = new AsyncFetchList(this);
	        groc_list.execute(id);
	    }
	  
	  public void fetchItems(long id) {
	        //progressBar.setVisibility(View.VISIBLE);
	        if (groc_item != null) {
	        	groc_item.cancel(true);
	        }
	        groc_item = new AsyncFetchItem(this);
	        groc_item.execute(id);
	    }
	  
	  public void SendTask(String task_name) {
	        //progressBar.setVisibility(View.VISIBLE);
	        //if (task != null) {
	          //  task.cancel(true);
	        //}
	        send_task_thread = new AsyncSendTask(this);
	        
	        send_task_thread.execute(task_name);
	    }
	  
	  public void SendList(String task_name, String user_id) {
	        //progressBar.setVisibility(View.VISIBLE);
	        //if (task != null) {
	          //  task.cancel(true);
	        //}
	        send_list_thread = new AsyncSendList(this);
	        
	        send_list_thread.execute(task_name, user_id);
	    }
	  
	  public void SendItem(String task_name, String listid, String check_state, String type) {
	        //progressBar.setVisibility(View.VISIBLE);
	        //if (task != null) {
	          //  task.cancel(true);
	        //}
	        send_item_thread = new AsyncSendItem(this);
	        
	        send_item_thread.execute(task_name, listid, check_state, type);
	    }
	  
	 
	  
	   public void compare_users(List<TaskProxy> tasks) throws InterruptedException {
		   
		   System.out.println("Users going...");
		   Cursor local_cursor ;
		   Cursor local_cursor2 ;
		   Cursor local_cursor3;
		   
		   //Traverse through local_cursor and tasks and compare names, if same name conflict
		   
		   //If on global but not on local, add to local
		   
		   //If on local but not on global, add to global
		   System.out.println(tasks.size());
		  // progressBar.setVisibility(View.VISIBLE);
		   int sync_index, id_index, did3_index;
		   long current_Did;
		  String current_name;
		  
		  local_cursor3 = mDb.fetchAllUsers();
		  local_cursor3.moveToFirst();
		  did3_index = local_cursor3.getColumnIndex(Database.KEY_DID);
		  List<Long> To_be_Deleted_Android = new ArrayList<Long>();
		  while(!local_cursor3.isAfterLast())
		  {
			  To_be_Deleted_Android.add(local_cursor3.getLong(did3_index));
			  local_cursor3.moveToNext();
		  }
		   System.out.println("Made it here");
		  //Adding/Updating users in app engine into Android
		   for (int i = 0; i < tasks.size(); i++) 
		   {
				//System.out.println(lList.get(i));
			  current_name = tasks.get(i).getName();
			  current_Did = tasks.get(i).getId();
			  To_be_Deleted_Android.remove(current_Did);
			  long current_date = tasks.get(i).getDueDate();
			  //local_cursor = mDb.fetchUser(current_name);
			  local_cursor = mDb.fetchUserByDid(current_Did);
			  sync_index = local_cursor.getColumnIndexOrThrow(Database.KEY_SYNC);
			  id_index = local_cursor.getColumnIndex(Database.KEY_USERID);
			  int date_index = local_cursor.getColumnIndex(Database.KEY_DATE);
			 
			   //Updating 
			  if(local_cursor.getCount()!=0)
			  {
				  local_cursor.moveToFirst();
				 // MyTools.displayToastMessage(myContext,"sync_index = "+ sync_index);
				  if(local_cursor.getString(sync_index).compareTo(Database.YES)!=0)  //Local item does not need to sync so update otherwise arbitrate
				  {
					  MyTools.displayToastMessage(myContext,"Sync value = "+ local_cursor.getString(sync_index));
					  mDb.updateUserFromSync(local_cursor.getInt(id_index), current_name);
					  
					  MyTools.displayToastMessage(myContext,"Updating to "+ tasks.get(i).getName());
				  }
				  else
				  {
					  MyTools.displayToastMessage(myContext, "Arbitrate");
					  MyTools.displayToastMessage(myContext, "current_date = "+current_date);
					  MyTools.displayToastMessage(myContext, "local_date = "+local_cursor.getLong(date_index));
					  if(current_date>local_cursor.getLong(date_index))
					  {
						  MyTools.displayToastMessage(myContext, "App Engine won");
						  mDb.updateUserFromSync(local_cursor.getInt(id_index), current_name);  
					  }
					  else
					  {
						  //Do nothing...will send to server below.
					  }
					  //Arbitration here based on dates
				  }
				  
				  //MyTools.displayToastMessage(myContext, tasks.get(i).getName());
				  //Users with same name exist handle this later
			  }
			  //Creating
			  else
			  {
				  if(mDb.User_Dids_tobe_Deleted.contains(current_Did))
				  {
					  //Delete
					  final long del_did = current_Did;
					  new AsyncTask<Void, Void, Void>() {

		                   @Override
		                    protected Void doInBackground(Void... arguments){
		                        CloudTasksRequestFactory factory = (CloudTasksRequestFactory) Util
		                                .getRequestFactory(UsersDisplayActivity.this,
		                                        CloudTasksRequestFactory.class);
		                        TaskRequest request = factory.taskRequest();

		                        TaskProxy task = request.create(TaskProxy.class);
		                       // task.setName(up_name);
		                        task.setId(del_did);
		                        //task.setNote(taskDetails);
		                       // task.setDueDate(dueDate);

		                        request.deleteTask(task).fire();
		                       // MyTools.displayToastMessage(myContext,"Sending "+ local_cursor2.getString(name_index) +" to server");

		                        return null;
		                    }

		                }.execute();
		                
					  
					  
					  mDb.User_Dids_tobe_Deleted.remove(current_Did);
				  }
				  else
				  {
					  mDb.createSyncUser(current_name, current_Did);
						 // mDb.createUser(tasks.get(i).getName());
					  MyTools.displayToastMessage(myContext,"Adding "+ tasks.get(i).getName());
				  }
				  
				
			  }
			  DBcursor.requery(); 
			}
		   
		   //Delete users in Android
		   if(!To_be_Deleted_Android.isEmpty())
		   {
			   for(int i=0;i<To_be_Deleted_Android.size();++i)
			   {
				   if(To_be_Deleted_Android.get(i)!=0)  //Then the user was not recently created on Android, otherwise delete
				   {
					  
					   mDb.deleteUserByDid(To_be_Deleted_Android.get(i));
				   }
				   
			   }
			   
		   }		   
		 //Adding/Updating users in app engine from Android	  
		  
		   local_cursor2=mDb.fetchAllUsersForSync();  //All these users have won arbitration so no need to arbitrate
		   
		   String name;
		   boolean match = false;
	       final int name_index = local_cursor2.getColumnIndex(Database.KEY_NAME);
	       int id_index2 = local_cursor2.getColumnIndex(Database.KEY_USERID);
	       final int did_index = local_cursor2.getColumnIndex(Database.KEY_DID);
	       int date_index = local_cursor2.getColumnIndex(Database.KEY_DATE);
		   local_cursor2.moveToFirst();
	        while (local_cursor2.isAfterLast() == false) {
	        	//MyTools.displayToastMessage(myContext,"Sending...");
	        	if(local_cursor2.getLong(did_index)==0)//Created on Android side but never synced on app engine
	        	{
	        		//Add to app engine, maybe add to list first...somehow get the did back after created on app engine side
	        		
	        		    users_ids.add(local_cursor2.getLong(id_index2));
	        			//current_user_id= local_cursor2.getLong(id_index2);
	        			MyTools.displayToastMessage(myContext,"Sending...");
	        			sync_count.increment();
	        			System.out.println("Incremented sync = "+sync_count.value());
	        			SendTask(local_cursor2.getString(name_index));
	        			//This allows this thread to block until it receives signal from SendTask
	        			synchronized (this) {
	        				
	        					this.wait(1000);
	        				
	        				}
	        			
	        			
	        		
	        	}
	        	else  //Updating a user b/c either already previously synced with app engine or created on app engine side
	        	{
	        		//Update users in app engine...maybe build list first
	        		//Don't have to check for arbitration, if gotten this far then it is master
	        		//StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);	
	        		final String up_name = local_cursor2.getString(name_index);
	        		final long up_did = local_cursor2.getLong(did_index);
	        		mDb.updateUserFromSync(local_cursor2.getInt(id_index2), local_cursor2.getString(name_index));//sets sync to no
	        		new AsyncTask<Void, Void, Void>() {

	                   @Override
	                    protected Void doInBackground(Void... arguments){
	                        CloudTasksRequestFactory factory = (CloudTasksRequestFactory) Util
	                                .getRequestFactory(UsersDisplayActivity.this,
	                                        CloudTasksRequestFactory.class);
	                        TaskRequest request = factory.taskRequest();

	                        TaskProxy task = request.create(TaskProxy.class);
	                        task.setName(up_name);
	                        task.setId(up_did);
	                        //task.setNote(taskDetails);
	                       // task.setDueDate(dueDate);

	                        request.updateTask(task).fire();
	                       // MyTools.displayToastMessage(myContext,"Sending "+ local_cursor2.getString(name_index) +" to server");

	                        return null;
	                    }

	                }.execute();
	                
	        		
	        		
	        	}
	        	
	        	//Create_tasks_in_server(created_list)
	        	//Update_tasks_in_server(updated_list)
	        	if(local_cursor2.moveToNext()==false)
	        		break;
	        	
	        	
	        }
	      
	        //onResume();
	        DBcursor.requery(); 
	        //refresh screen
	       // progressBar.setVisibility(View.GONE);
	        //progressBar.setVisibility(View.VISIBLE);
	        //DBcursor = mDb.fetchAllUsers();
	        //adapter.setTasks(tasks);
	        //adapter.notifyDataSetChanged();
	        
	        list_go = 1;
	        ++sync_var;
	        System.out.println(sync_var);
	        int branch = 0;
	        //while(branch==0)
	        //{
	        	//if(sync_count.value()==0)
	        	//{
	        //while(sync_count.value()!=0){};
	        System.out.println("Users finished");
	        fetchLists(-1);
	        branch = 1;
	        	//}
	        //}
	        	
	       // notify();
	    }
	   
   public void compare_lists(List<ListProxy> tasks) throws InterruptedException {
	   
	 //  while(list_go!=1){
		//   try {
			//wait(1);
	//	} catch (InterruptedException e) {
			// TODO Auto-generated catch block
		//	e.printStackTrace();
		//}
	   //}  //spin here
	   System.out.println("Starting compare lists...");
	   Cursor local_cursor ;
	   Cursor local_cursor2 ;
	   Cursor local_cursor3;
	   
	   //Traverse through local_cursor and tasks and compare names, if same name conflict
	   
	   System.out.println(tasks.size());
	  // progressBar.setVisibility(View.VISIBLE);
	   int sync_index, id_index, did3_index;
	   long current_Did, current_userdid, current_userid;
	  String current_name;
	  
	  local_cursor3 = mDb.fetchAllLists();
	  local_cursor3.moveToFirst();
	  did3_index = local_cursor3.getColumnIndex(Database.KEY_DID);
	  List<Long> To_be_Deleted_Android = new ArrayList<Long>();
	  while(!local_cursor3.isAfterLast())
	  {
		  To_be_Deleted_Android.add(local_cursor3.getLong(did3_index));
		  local_cursor3.moveToNext();
	  }
	   System.out.println("Made it here");
	  //Adding/Updating users in app engine into Android
	   for (int i = 0; i < tasks.size(); i++) {
			//System.out.println(lList.get(i));
		  current_name = tasks.get(i).getName();
		  current_Did = tasks.get(i).getId();
		  current_userdid= tasks.get(i).getOwnerId();
		  Cursor curse_me = mDb.fetchUserByDid(current_userdid);
		  curse_me.moveToFirst();
		  if(curse_me.getCount()==0)
		  {
			  continue;
		  }
		  current_userid = curse_me.getLong(curse_me.getColumnIndex(Database.KEY_USERID));
		  To_be_Deleted_Android.remove(current_Did);
		  System.out.println(current_name);
		  long current_date = tasks.get(i).getDate();
		  //local_cursor = mDb.fetchUser(current_name);
		  local_cursor = mDb.fetchListByDid(current_Did);
		  sync_index = local_cursor.getColumnIndexOrThrow(Database.KEY_SYNC);
		  id_index = local_cursor.getColumnIndex(Database.KEY_USERID);
		  int date_index = local_cursor.getColumnIndex(Database.KEY_DATE);
		 
		   //Dids previously synced
		  // Updating 
		  if(local_cursor.getCount()!=0)
		  {
			  local_cursor.moveToFirst();
			 // MyTools.displayToastMessage(myContext,"sync_index = "+ sync_index);
			  if(local_cursor.getString(sync_index).compareTo(Database.YES)!=0)  //Local item does not need to sync so update otherwise arbitrate
			  {
				  MyTools.displayToastMessage(myContext,"Sync value = "+ local_cursor.getString(sync_index));
				  mDb.updateListFromSync(local_cursor.getInt(id_index), current_name);
				  
				  MyTools.displayToastMessage(myContext,"Updating to "+ tasks.get(i).getName());
			  }
			  else
			  {
				  MyTools.displayToastMessage(myContext, "Arbitrate");
				  MyTools.displayToastMessage(myContext, "current_date = "+current_date);
				  MyTools.displayToastMessage(myContext, "local_date = "+local_cursor.getLong(date_index));
				  if(current_date>local_cursor.getLong(date_index))
				  {
					  MyTools.displayToastMessage(myContext, "App Engine won");
					  mDb.updateListFromSync(local_cursor.getInt(id_index), current_name);  
				  }
				  else
				  {
					  //Do nothing...will send to server below.
				  }
				  //Arbitration here based on dates
			  }
			  
			  //MyTools.displayToastMessage(myContext, tasks.get(i).getName());
			  //Users with same name exist handle this later
		  }
		  //Creating
		  else
		  {
			  Long iddd = new Long(current_Did);
			  System.out.println(current_Did);
			  System.out.println(Database.List_Dids_tobe_Deleted2.size());
			  //System.out.println(mDb.List_Dids_tobe_Deleted2.get(0));
			  System.out.println(Database.List_Dids_tobe_Deleted2.contains(iddd));
			  if(Database.List_Dids_tobe_Deleted2.contains(iddd))
			  {
				  //Delete
				  System.out.println("Deleting...what's going on?");
				  final long del_did = current_Did;
				  new AsyncTask<Void, Void, Void>() {

	                   @Override
	                    protected Void doInBackground(Void... arguments){
	                        CloudTasksRequestFactory factory = (CloudTasksRequestFactory) Util
	                                .getRequestFactory(UsersDisplayActivity.this,
	                                        CloudTasksRequestFactory.class);
	                        ListRequest request = factory.listRequest();

	                        ListProxy task = request.create(ListProxy.class);
	                       // task.setName(up_name);
	                        task.setId(del_did);
	                        //task.setNote(taskDetails);
	                       // task.setDueDate(dueDate);
	                        
	                        request.deleteList(task).fire();
	                       // MyTools.displayToastMessage(myContext,"Sending "+ local_cursor2.getString(name_index) +" to server");

	                        return null;
	                    }

	                }.execute();
	                
				  Database.List_Dids_tobe_Deleted2.remove(current_Did);
			  }
			  else
			  {
				  System.out.println("Creating...what's going on?");
				  mDb.createSyncList(current_name, current_Did, current_userid);
					 // mDb.createUser(tasks.get(i).getName());
				  MyTools.displayToastMessage(myContext,"Adding "+ tasks.get(i).getName());
			  }
			  
			
		  }
		  //DBcursor.requery(); 
		}
	   
	   //Delete users in Android
	   if(!To_be_Deleted_Android.isEmpty())
	   {
		   for(int i=0;i<To_be_Deleted_Android.size();++i)
		   {
			   if(To_be_Deleted_Android.get(i)!=0)  //Then the user was not recently created on Android, otherwise delete
			   {
				  
				   mDb.deleteListByDid(To_be_Deleted_Android.get(i));
			   }
			   
		   }
		   
	   }		   
	 //Adding/Updating users in app engine from Android	  
	  
	   local_cursor2=mDb.fetchAllListsForSync();  //All these users have won arbitration so no need to arbitrate
	   
	   String name;
	   boolean match = false;
       final int name_index = local_cursor2.getColumnIndex(Database.KEY_NAME);
       int id_index2 = local_cursor2.getColumnIndex(Database.KEY_USERID);
       final int did_index = local_cursor2.getColumnIndex(Database.KEY_DID);
       int date_index = local_cursor2.getColumnIndex(Database.KEY_DATE);
       int userid_index = local_cursor2.getColumnIndex(Database.KEY_USER_NUM);
	   local_cursor2.moveToFirst();
        while (local_cursor2.isAfterLast() == false) {
        	//MyTools.displayToastMessage(myContext,"Sending...");
        	if(local_cursor2.getLong(did_index)==0)//Created on Android side but never synced on app engine
        	{
        		//Add to app engine, maybe add to list first...somehow get the did back after created on app engine side
        		//
        		
        		//if(lock2==0)
        		//{
        			//lock2 = 1;
        		//while(sync_count.value()!=0){};
        		//lock2=1;
    			//current_list_id= local_cursor2.getLong(id_index2);
    			list_ids.add(local_cursor2.getLong(id_index2));
    			long userid = local_cursor2.getLong(userid_index);
    			long userdid=0;
    			//while(userdid == 0)
    			//{
    				Cursor curse = mDb.fetchUser2(userid);
    				curse.moveToFirst();
    				userdid = curse.getLong(curse.getColumnIndex(Database.KEY_DID));
    			//}
    			MyTools.displayToastMessage(myContext,"Sending List...");
    			sync_count.increment();
    			System.out.println("Incrementing sync list =" + sync_count.value());
    			SendList(local_cursor2.getString(name_index), Long.toString(userdid));
    			synchronized (this) {
    				
					this.wait(1000);
				
				}
    			
        		
        			
        			
        		//}
        		
        		
        	}
        	else  //Updating a user b/c either already previously synced with app engine or created on app engine side
        	{
        		//Update users in app engine...maybe build list first
        		//Don't have to check for arbitration, if gotten this far then it is master
        		//StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);	
        		final String up_name = local_cursor2.getString(name_index);
        		long userid = local_cursor2.getLong(userid_index);
    			Cursor curse = mDb.fetchUser2(userid);
    			curse.moveToFirst();
    			long userdid = curse.getLong(curse.getColumnIndex(Database.KEY_DID));
        		long did = local_cursor2.getLong(did_index);
        		
        		final long up_did = userdid;
        		final long up_list_did = did;
        		mDb.updateListFromSync(local_cursor2.getInt(id_index2), local_cursor2.getString(name_index));//sets sync to no
        		new AsyncTask<Void, Void, Void>() {

                   @Override
                    protected Void doInBackground(Void... arguments){
                        CloudTasksRequestFactory factory = (CloudTasksRequestFactory) Util
                                .getRequestFactory(UsersDisplayActivity.this,
                                        CloudTasksRequestFactory.class);
                        ListRequest request = factory.listRequest();

                        ListProxy task = request.create(ListProxy.class);
                        task.setName(up_name);
                        task.setId(up_list_did);
                        task.setOwnerId(up_did);
                        //task.setNote(taskDetails);
                       // task.setDueDate(dueDate);

                        request.updateList(task).fire();
                       // MyTools.displayToastMessage(myContext,"Sending "+ local_cursor2.getString(name_index) +" to server");

                        return null;
                    }

                }.execute();
                
        		
        		
        	}
        	
        	//Create_tasks_in_server(created_list)
        	//Update_tasks_in_server(updated_list)
        	if(local_cursor2.moveToNext()==false)
        		break;
        	
        	
        }
      
        item_go = 1;
        ++sync_var;
       // while(sync_count.value()!=0){};
        
        fetchItems(-1);
        //notify();
        //onResume();
        //DBcursor.requery(); 
        //refresh screen
       
        //progressBar.setVisibility(View.VISIBLE);
        //DBcursor = mDb.fetchAllUsers();
        //adapter.setTasks(tasks);
        //adapter.notifyDataSetChanged();
	    }
   
   
   public void compare_items(List<ItemProxy> tasks) {
	   
	  // while(item_go!=1){};  //spin here
	   System.out.println("Starting compare items...");
	   
	   Cursor local_cursor ;
	   Cursor local_cursor2 ;
	   Cursor local_cursor3;
	   
	   //Traverse through local_cursor and tasks and compare names, if same name conflict
	   
	   System.out.println(tasks.size());
	  // progressBar.setVisibility(View.VISIBLE);
	   int sync_index, id_index, did3_index;
	   long current_Did, current_listdid, current_listid;
	  String current_name, current_type;
	  
	  local_cursor3 = mDb.fetchAllItems();
	  local_cursor3.moveToFirst();
	  did3_index = local_cursor3.getColumnIndex(Database.KEY_DID);
	  List<Long> To_be_Deleted_Android = new ArrayList<Long>();
	  while(!local_cursor3.isAfterLast())
	  {
		  To_be_Deleted_Android.add(local_cursor3.getLong(did3_index));
		  local_cursor3.moveToNext();
	  }
	  // System.out.println("Made it here");
	  //Adding/Updating items in app engine into Android
	   for (int i = 0; i < tasks.size(); i++) {
			//System.out.println(lList.get(i));
		  current_name = tasks.get(i).getName();
		  current_Did = tasks.get(i).getId();
		  current_listdid= tasks.get(i).getListId();
		  current_type = tasks.get(i).getType();
		  Cursor curse_me = mDb.fetchListByDid(current_listdid);
		  curse_me.moveToFirst();
		  current_listid = curse_me.getLong(curse_me.getColumnIndex(Database.KEY_USERID));
		  To_be_Deleted_Android.remove(current_Did);
		  System.out.println(current_name);
		  long current_date = tasks.get(i).getDate();
		  //local_cursor = mDb.fetchUser(current_name);
		  local_cursor = mDb.fetchItemByDid(current_Did);
		  sync_index = local_cursor.getColumnIndexOrThrow(Database.KEY_SYNC);
		  id_index = local_cursor.getColumnIndex(Database.KEY_USERID);
		  int date_index = local_cursor.getColumnIndex(Database.KEY_DATE);
		 
		   //Dids previously synced
		  // Updating 
		  if(local_cursor.getCount()!=0)
		  {
			  local_cursor.moveToFirst();
			 // MyTools.displayToastMessage(myContext,"sync_index = "+ sync_index);
			  if(local_cursor.getString(sync_index).compareTo(Database.YES)!=0)  //Local item does not need to sync so update otherwise arbitrate
			  {
				  MyTools.displayToastMessage(myContext,"Sync value = "+ local_cursor.getString(sync_index));
				  mDb.updateItemFromSync(local_cursor.getInt(id_index), current_name);
				  
				  MyTools.displayToastMessage(myContext,"Updating to "+ tasks.get(i).getName());
			  }
			  else
			  {
				  MyTools.displayToastMessage(myContext, "Arbitrate");
				  MyTools.displayToastMessage(myContext, "current_date = "+current_date);
				  MyTools.displayToastMessage(myContext, "local_date = "+local_cursor.getLong(date_index));
				  if(current_date>local_cursor.getLong(date_index))
				  {
					  MyTools.displayToastMessage(myContext, "App Engine won");
					  mDb.updateItemFromSync(local_cursor.getInt(id_index), current_name);  
				  }
				  else
				  {
					  //Do nothing...will send to server below.
				  }
				  //Arbitration here based on dates
			  }
			  
			  //MyTools.displayToastMessage(myContext, tasks.get(i).getName());
			  //Users with same name exist handle this later
		  }
		  //Creating
		  else
		  {
			 
			  if(Database.Item_Dids_tobe_Deleted.contains(current_Did))
			  {
				  //Delete
				  System.out.println("Deleting...");
				  final long del_did = current_Did;
				  new AsyncTask<Void, Void, Void>() {

	                   @Override
	                    protected Void doInBackground(Void... arguments){
	                        CloudTasksRequestFactory factory = (CloudTasksRequestFactory) Util
	                                .getRequestFactory(UsersDisplayActivity.this,
	                                        CloudTasksRequestFactory.class);
	                        TaskRequest request = factory.taskRequest();

	                        ItemProxy task = request.create(ItemProxy.class);
	                       // task.setName(up_name);
	                        task.setId(del_did);
	                        //task.setNote(taskDetails);
	                       // task.setDueDate(dueDate);
	                        
	                        request.deleteItem(task).fire();
	                       // MyTools.displayToastMessage(myContext,"Sending "+ local_cursor2.getString(name_index) +" to server");

	                        return null;
	                    }

	                }.execute();
	                
				  Database.Item_Dids_tobe_Deleted.remove(current_Did);
			  }
			  else
			  {
				  System.out.println("Creating...");
				  mDb.createSyncItem(current_name, current_Did, current_listid, current_type );
					 // mDb.createUser(tasks.get(i).getName());
				  MyTools.displayToastMessage(myContext,"Adding "+ tasks.get(i).getName());
			  }
			  
			
		  }
		  //DBcursor.requery(); 
		}
	   
	   //Delete users in Android
	   if(!To_be_Deleted_Android.isEmpty())
	   {
		   for(int i=0;i<To_be_Deleted_Android.size();++i)
		   {
			   if(To_be_Deleted_Android.get(i)!=0)  //Then the user was not recently created on Android, otherwise delete
			   {
				  
				   mDb.deleteItemByDid(To_be_Deleted_Android.get(i));
			   }
			   
		   }
		   
	   }		   
	 //Adding/Updating users in app engine from Android	  
	  
	   local_cursor2=mDb.fetchAllItemsForSync();  //All these items have won arbitration so no need to arbitrate
	   
	   String name;
	   boolean match = false;
       final int name_index = local_cursor2.getColumnIndex(Database.KEY_GROC_NAME);
       int id_index2 = local_cursor2.getColumnIndex(Database.KEY_USERID);
       final int did_index = local_cursor2.getColumnIndex(Database.KEY_DID);
       int type_index = local_cursor2.getColumnIndex(Database.KEY_TYPE);
       int listid_index = local_cursor2.getColumnIndex(Database.KEY_LIST_NUM);
       int check_index = local_cursor2.getColumnIndex(Database.KEY_CHECKED);
	   local_cursor2.moveToFirst();
       
	   while (local_cursor2.isAfterLast() == false) 
        {
        	//MyTools.displayToastMessage(myContext,"Sending...");
        	if(local_cursor2.getLong(did_index)==0)//Created on Android side but never synced on app engine
        	{
        		//Add to app engine, maybe add to list first...somehow get the did back after created on app engine side
        		//while(sync_count.value()!=0){};
        		item_ids.add(local_cursor2.getLong(id_index2));  //My queue for capturing dids later on
    			//current_item_id= local_cursor2.getLong(id_index2);
    			long listid = local_cursor2.getLong(listid_index);
    			Cursor curse = mDb.fetchList2(listid);
    			if(curse.getCount()!=0)
    			{
    				curse.moveToFirst();
    				long listdid = curse.getLong(curse.getColumnIndex(Database.KEY_DID));
    				long checked = local_cursor2.getLong(check_index);
    				sync_count.increment();
    				
    				SendItem(local_cursor2.getString(name_index), Long.toString(listdid), Long.toString(checked), local_cursor2.getString(type_index) );
    			}
        		//while(lock2==1) {};
        			
        			
        		//}
        		
        		
        	}
        	else  //Updating a user b/c either already previously synced with app engine or created on app engine side
        	{
        		//Update users in app engine...maybe build list first
        		//Don't have to check for arbitration, if gotten this far then it is master
        		//StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);	
        		
        		final String up_name = local_cursor2.getString(name_index);
        		long listid = local_cursor2.getLong(listid_index);
    			Cursor curse = mDb.fetchList2(listid);
    			curse.moveToFirst();
    			long listdid = curse.getLong(curse.getColumnIndex(Database.KEY_DID));
        		long did = local_cursor2.getLong(did_index);
        		
        		final long up_did = listdid;
        		final long up_item_did = did;
        		final String type = local_cursor2.getString(type_index);
        		final boolean b = (local_cursor2.getLong(check_index)==1);
        		mDb.updateItemFromSync(local_cursor2.getInt(id_index2), local_cursor2.getString(name_index));//sets sync to no
        		new AsyncTask<Void, Void, Void>() {

                   @Override
                    protected Void doInBackground(Void... arguments){
                        CloudTasksRequestFactory factory = (CloudTasksRequestFactory) Util
                                .getRequestFactory(UsersDisplayActivity.this,
                                        CloudTasksRequestFactory.class);
                        TaskRequest request = factory.taskRequest();

                        ItemProxy task = request.create(ItemProxy.class);
                        task.setName(up_name);
                        task.setId(up_item_did);
                        task.setListId(up_did);
                        task.setType(type);
                        task.setchecked(b);
                        //task.setNote(taskDetails);
                       // task.setDueDate(dueDate);

                        request.updateItem(task).fire();
                       // MyTools.displayToastMessage(myContext,"Sending "+ local_cursor2.getString(name_index) +" to server");

                        return null;
                    }

                }.execute();
                
        		
        		
        	}
        	
        	//Create_tasks_in_server(created_list)
        	//Update_tasks_in_server(updated_list)
        	if(local_cursor2.moveToNext()==false)
        		break;
        	
        	
        }
      
        //onResume();
        //DBcursor.requery(); 
        //refresh screen
        System.out.println("Finished compare items");
        progressBar.setVisibility(View.GONE);
        sync_var= 0;
        //progressBar.setVisibility(View.VISIBLE);
        //DBcursor = mDb.fetchAllUsers();
        //adapter.setTasks(tasks);
        //adapter.notifyDataSetChanged();
	    }
	   
	  
	   
	   public void update_user(Long user)
	   {
		   mDb.updateUserDid(users_ids.remove(), user);  //Updates the did from datastore...therefore datastore has master index
		   System.out.println("New did =" +user);
		   System.out.println("Stop blocking");
		   //sync_count.decrement();
		   //lock=0;
		   return;
	   }
	   
	   public void update_list(Long list_did)
	   {
		   mDb.updateListDid(list_ids.remove(), list_did);  //Updates the did from datastore...therefore datastore has master index
		   lock2=0;
		   return;
	   }
	   
	   public void update_item(Long item_did)
	   {
		   mDb.updateItemDid(item_ids.remove(), item_did);  //Updates the did from datastore...therefore datastore has master index
		   lock3=0;
		   return;
	   }
	   
	   @Override
	    protected void onResume() {
	        super.onResume();
	        lv.refreshDrawableState();
	        //DBcursor.requery();
	    }
	   
	   
	
}
